import { customRef, watch } from 'vue'

import type { IEventDebounce } from '../../types/20-form-child'

/**
 * 直接修改 model 的防抖
 * @param model 组件的 props 的 model
 * @param colName 需要使用的属性名称
 * @param events 事件集合，run：立即提交；clear：清空计时，用于汉字输入
 * @param delay 延迟时间，默认 500 毫秒
 */
export default function debounceRef<T, K extends keyof T>
(
  model: T,
  colName: K,
  events: IEventDebounce,
  delay = 500
) {

  // 计时器
  let timeout: NodeJS.Timeout
  // 初始化设置属性值
  let _value: T[K] = model[colName]
  
  // 立即提交的事件
  events.run = () => {
    // 清掉上一次的计时
    clearTimeout(timeout)
    // 立即提交
    model[colName] = _value
  }

  // 清掉上次计时，用于汉字的连续输入
  events.clear = () => {
    clearTimeout(timeout) // 清掉上一次的计时
  }
  
  return customRef<T[K]>((track: () => void, trigger: () => void) => {
    // 监听父组件的属性变化，然后赋值，确保响应父组件设置属性
    watch(() => model[colName], (v1) => {
      _value = v1
      trigger()
    })

    return {
      get(): T[K] {
        track()
        return _value
      },
      set(val: T[K]) {
        _value = val // 绑定值
        trigger() // 输入内容绑定到控件，但是不提交
        clearTimeout(timeout) // 清掉上一次的计时
        // 设置新的计时
        timeout = setTimeout(() => {
          model[colName] = _value // 提交
        }, delay)
      }
    }
  })
}
